home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / emulation / frodo / src / 6581.asm < prev    next >
Assembly Source File  |  1996-01-29  |  9KB  |  516 lines

  1. *
  2. * 6581.asm - SID-Emulation
  3. *
  4. * Copyright (C) 1994-1996 by Christian Bauer
  5. *
  6.  
  7. *
  8. * Anmerkungen:
  9. * ------------
  10. *
  11. * Funktionsprinzip:
  12. *  - Es bestehen vier Möglichkeiten zur SID-Emulation, die über das
  13. *    Flag UseSIDCard ausgewählt werden: Keine Emulation (d.h. kein Ton),
  14. *    die Verwendung der SID-Karte, die "6581sid.library" und die
  15. *    "playsid.library"
  16. *
  17. * SID-Karte:
  18. *  - Die SID-Karte enthält einen echten C64-SID, der im Adreßraum
  19. *    $a00001-$a00039 (Register an den ungeraden Adressen) eingeblendet
  20. *    ist (z.B. auf einer Zorro-II-Karte)
  21. *  - Wegen Timing-Problemen mit der Karte werden Lesezugriffe aus
  22. *    SID-Registern nur simuliert
  23. *  - Die Power-LED ist mit dem Reset-Eingang des SID verbunden,
  24. *    d.h. ein kurzes Aus- und Einschalten der LED setzt den SID
  25. *    zurück
  26. *
  27. * PlaySID:
  28. *  - Da die playsid.library keinen Befehl zum direkten Setzen von SID-
  29. *    Registern hat, wird ein Trick angewendet: Es wird ein Dummy-Modul
  30. *    installiert, dessen Play-Routine nur die Aufgabe hat, ein einziges
  31. *    SID-Register zu setzen. Schreibt der Prozessor in ein SID-Register,
  32. *    werden Registernummer und Wert in die Play-Routine im C64-RAM der
  33. *    playsid.library geschrieben und über ForwardSong ein Aufruf der
  34. *    Play-Routine erzwungen
  35. *
  36.  
  37.         MACHINE    68020
  38.  
  39.         INCLUDE    "exec/types.i"
  40.         INCLUDE    "exec/macros.i"
  41.         INCLUDE    "exec/nodes.i"
  42.         INCLUDE    "libraries/playsidbase.i"
  43.         INCLUDE    "libraries/playsid_lib.i"
  44.         INCLUDE    "hardware/intbits.i"
  45.  
  46.         XREF    _SysBase
  47.         XREF    _GfxBase
  48.         XREF    _SID6581Base
  49.         XREF    _PlaySidBase
  50.  
  51.         XREF    Random
  52.  
  53.         XDEF    Reset6581
  54.         XDEF    ReadFrom6581
  55.         XDEF    WriteTo6581
  56.         XDEF    _PauseSound
  57.         XDEF    _ResumeSound
  58.         XDEF    _GetSIDDump
  59.         XDEF    InitSID
  60.         XDEF    ExitSID
  61.         XDEF    ChangedSIDPrefs
  62.         XDEF    SIDType        ;Prefs
  63.  
  64.         SECTION    "text",CODE
  65.  
  66. *
  67. * Definitionen
  68. *
  69.  
  70. ; SIDType
  71. SIDTYPE_OFF    = 0    ;Audio-Ausgabe aus
  72. SIDTYPE_CARD    = 1    ;SID-Karte
  73. SIDTYPE_A64    = 2    ;6581sid.library
  74. SIDTYPE_PSID    = 3    ;playsid.library
  75.  
  76. ; 6581sid.library
  77. SID_AllocSID    = -30
  78. SID_FreeSID    = -36
  79. SID_Interrupt    = -42
  80. SID_Initialize    = -48
  81. SID_ResetSID    = -54
  82. SID_IRQOnOff    = -60
  83. SID_ReadReg    = -72
  84. SID_WriteReg    = -78
  85.  
  86. ; SID Handle Struktur
  87. sid_Enabled    = 4
  88. sid_Filter    = 5
  89. sid_60Hz    = 6
  90. sid_RingQual    = 7
  91. sid_SyncQual    = 8
  92. sid_ADSRQual    = 13
  93. sid_IRQRate    = 18
  94.  
  95.  
  96. **
  97. ** SID-Emulation starten
  98. **
  99.  
  100. InitSID        move.w    SIDType,CurrentSIDType
  101.         bsr    OpenSID
  102.         st.b    SIDInited
  103.         rts
  104.  
  105.  
  106. **
  107. ** SID-Emulation beenden
  108. **
  109.  
  110. ExitSID        tst.b    SIDInited
  111.         beq    1$
  112.         bsr    CloseSID
  113. 1$        rts
  114.  
  115.  
  116. **
  117. ** SID-Einstellungen wurde verändert
  118. **
  119.  
  120. ; Schließen und neu öffnen, wenn sich die Einstellungen geändert haben
  121. ChangedSIDPrefs    move.w    SIDType,d0
  122.         cmp.w    CurrentSIDType,d0
  123.         beq    1$
  124.         bsr    CloseSID
  125.         move.w    SIDType,CurrentSIDType
  126.         bsr    OpenSID
  127. 1$        rts
  128.  
  129.  
  130. *
  131. * Alles für SID-Emulation mit CurrentSIDType vorbereiten
  132. *
  133.  
  134. OpenSID        cmp.w    #SIDTYPE_A64,CurrentSIDType
  135.         beq    OpenA64
  136.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  137.         beq    OpenPSID
  138.         rts
  139.  
  140. OpenA64        move.l    _SID6581Base,d0        ;6581sid.library offen?
  141.         beq    1$
  142.  
  143.         move.l    a6,-(sp)        ;Ja, SIDHandle holen
  144.         move.l    d0,a6
  145.         jsr    SID_AllocSID(a6)
  146.         move.l    d0,SIDHandle
  147.         beq    2$
  148.  
  149.         move.l    d0,a1            ;Parameter setzen
  150.         st.b    sid_Enabled(a1)
  151.         clr.b    sid_Filter(a1)
  152.         st.b    sid_60Hz(a1)
  153.         move.b    #48,sid_RingQual(a1)
  154.         move.b    #48,sid_SyncQual(a1)
  155.         move.b    #48,sid_ADSRQual(a1)
  156.         move.w    #60,sid_IRQRate(a1)
  157.         jsr    SID_Initialize(a6)
  158.  
  159.         move.l    SIDHandle,a1        ;SID anschalten
  160.         moveq    #0,d0
  161.         jsr    SID_IRQOnOff(a6)
  162.  
  163.         move.l    _SysBase,a6        ;VBI einrichten
  164.         lea    VBInterrupt,a1
  165.         moveq    #INTB_VERTB,d0
  166.         JSRLIB    AddIntServer
  167.  
  168. 2$        move.l    (sp)+,a6
  169. 1$        rts
  170.  
  171. OpenPSID    clr.b    PSIDOpened
  172.  
  173.         move.l    _PlaySidBase,d0        ;playsid.library offen?
  174.         beq    1$
  175.  
  176.         move.l    a6,-(sp)
  177.         move.l    d0,a6            ;Ja, Resourcen belegen
  178.         jsr    _LVOAllocEmulResource(a6)
  179.         tst.l    d0
  180.         bne    2$
  181.  
  182.         lea    PSIDHeader,a0        ;"Modul" setzen
  183.         move.l    a0,a1
  184.         move.l    #PSIDEnd-PSIDHeader,d0
  185.         jsr    _LVOSetModule(a6)
  186.  
  187.         moveq    #1,d0            ;Und starten
  188.         jsr    _LVOStartSong(a6)
  189.         tst.l    d0
  190.         beq    3$
  191.  
  192.         jsr    _LVOFreeEmulResource(a6) ;Nicht gelungen
  193.         bra    2$
  194.  
  195. 3$        bset    #1,$bfe001        ;Filter aus
  196.         st.b    PSIDOpened
  197.  
  198. 2$        move.l    (sp)+,a6
  199. 1$        rts
  200.  
  201.  
  202. *
  203. * SID-Emulation mit CurrentSIDType beenden
  204. *
  205.  
  206. CloseSID    cmp.w    #SIDTYPE_A64,CurrentSIDType
  207.         beq    CloseA64
  208.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  209.         beq    ClosePSID
  210.         rts
  211.  
  212. CloseA64    move.l    SIDHandle,d0
  213.         beq    1$
  214.  
  215.         move.l    a6,-(sp)
  216.         move.l    _SID6581Base,a6        ;SID abschalten
  217.         move.l    d0,a1
  218.         moveq    #-1,d0
  219.         jsr    SID_IRQOnOff(a6)
  220.  
  221.         move.l    _SysBase,a6        ;VBI entfernen
  222.         lea    VBInterrupt,a1
  223.         moveq    #INTB_VERTB,d0
  224.         JSRLIB    RemIntServer
  225.  
  226.         move.l    _SID6581Base,a6
  227.         move.l    SIDHandle,a1        ;Und SIDHandle freigeben
  228.         jsr    SID_FreeSID(a6)
  229.         clr.l    SIDHandle
  230.         move.l    (sp)+,a6
  231. 1$        rts
  232.  
  233. ClosePSID    tst.b    PSIDOpened
  234.         beq    1$
  235.  
  236.         move.l    a6,-(sp)
  237.         move.l    _PlaySidBase,a6
  238.         jsr    _LVOStopSong(a6)    ;Alles freigeben
  239.         jsr    _LVOFreeEmulResource(a6)
  240.         bclr    #1,$bfe001        ;Filter an
  241.         clr.b    PSIDOpened
  242.         move.l    (sp)+,a6
  243. 1$        rts
  244.  
  245.  
  246. *
  247. * Interrupt-Routine
  248. * a1: SIDHandle
  249. *
  250.  
  251. IntProc        move.l    _SID6581Base,a6
  252.         jsr    SID_Interrupt(a6)
  253.         moveq    #0,d0            ;Nächsten Server aufrufen
  254.         rts
  255.  
  256.  
  257. **
  258. ** Sound stummschalten
  259. **
  260.  
  261. _PauseSound    cmp.w    #SIDTYPE_A64,CurrentSIDType
  262.         beq    PauseA64
  263.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  264.         beq    PausePSID
  265.         rts
  266.  
  267. PauseA64    move.l    SIDHandle,d0
  268.         beq    1$
  269.         move.l    a6,-(sp)
  270.         move.l    _SID6581Base,a6
  271.         move.l    d0,a1
  272.         moveq    #-1,d0
  273.         jsr    SID_IRQOnOff(a6)
  274.         move.l    (sp)+,a6
  275. 1$        rts
  276.  
  277. PausePSID    tst.b    PSIDOpened
  278.         beq    1$
  279.         move.l    a6,-(sp)
  280.         move.l    _PlaySidBase,a6
  281.         jsr    _LVOPauseSong(a6)
  282.         move.l    (sp)+,a6
  283. 1$        rts
  284.  
  285.  
  286. **
  287. ** Sound wieder laut machen
  288. **
  289.  
  290. _ResumeSound    cmp.w    #SIDTYPE_A64,CurrentSIDType
  291.         beq    ResumeA64
  292.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  293.         beq    ResumePSID
  294.         rts
  295.  
  296. ResumeA64    move.l    SIDHandle,d0
  297.         beq    1$
  298.         move.l    a6,-(sp)
  299.         move.l    _SID6581Base,a6
  300.         move.l    d0,a1
  301.         moveq    #0,d0
  302.         jsr    SID_IRQOnOff(a6)
  303.         move.l    (sp)+,a6
  304. 1$        rts
  305.  
  306. ResumePSID    tst.b    PSIDOpened
  307.         beq    1$
  308.         move.l    a6,-(sp)
  309.         move.l    _PlaySidBase,a6
  310.         jsr    _LVOContinueSong(a6)
  311.         move.l    (sp)+,a6
  312. 1$        rts
  313.  
  314.  
  315. **
  316. ** SID zurücksetzen
  317. **
  318.  
  319. Reset6581    lea    Registers,a0
  320.         moveq    #32/4-1,d0
  321. 1$        clr.l    (a0)+
  322.         dbra    d0,1$
  323.  
  324.         cmp.w    #SIDTYPE_CARD,CurrentSIDType
  325.         beq    ResetCard
  326.         cmp.w    #SIDTYPE_A64,CurrentSIDType
  327.         beq    ResetA64
  328.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  329.         beq    ResetPSID
  330.         rts
  331.  
  332. ResetCard    move.l    a6,-(sp)
  333.         move.l    _GfxBase,a6
  334.         JSRLIB    WaitTOF
  335.         bset    #1,$bfe001    ;LED aus
  336.         JSRLIB    WaitTOF
  337.         bclr    #1,$bfe001    ;LED an
  338.         move.l    (sp)+,a6
  339.         rts
  340.  
  341. ResetA64    move.l    SIDHandle,d0
  342.         beq    1$
  343.         move.l    a6,-(sp)
  344.         move.l    _SID6581Base,a6
  345.         move.l    d0,a1
  346.         jsr    SID_ResetSID(a6)
  347.         move.l    (sp)+,a6
  348. 1$        rts
  349.  
  350. ResetPSID    tst.b    PSIDOpened
  351.         beq    1$
  352.         move.l    a6,-(sp)
  353.         move.l    _PlaySidBase,a6
  354.         jsr    _LVOStopSong(a6)
  355.         moveq    #1,d0
  356.         jsr    _LVOStartSong(a6)
  357.         move.l    (sp)+,a6
  358. 1$        rts
  359.  
  360.  
  361. **
  362. ** SID-Status in Datenstruktur schreiben
  363. **
  364.  
  365. _GetSIDDump    move.l    4(sp),a1
  366.         lea    Registers,a0
  367.  
  368.         moveq    #24,d0        ;freq_lo_1 bis mode_vol
  369. 1$        move.b    (a0)+,(a1)+
  370.         dbra    d0,1$
  371.  
  372.         st    (a1)+        ;pot_x
  373.         st    (a1)+        ;pot_y
  374.         clr.b    (a1)+        ;osc_3
  375.         clr.b    (a1)        ;env_3
  376.         rts
  377.  
  378.  
  379. **
  380. ** Aus einem SID-Register lesen
  381. ** d0.w: Registernummer ($00-$1f)
  382. ** Rückgabe: d0.b: Byte
  383. **
  384. ** Darf das obere Wort von d0 und d1 nicht verändern!
  385. **
  386.  
  387. ReadFrom6581    cmp.b    #$19,d0
  388.         beq    ReadFF
  389.         cmp.b    #$1a,d0
  390.         beq    ReadFF
  391.         cmp.b    #$1b,d0
  392.         beq    ReadRnd
  393.         moveq    #0,d0
  394.         rts
  395.  
  396. ReadFF        move.b    #-1,d0        ;A/D-Wandler
  397.         rts
  398.  
  399. ReadRnd        jsr    Random
  400.         moveq    #0,d1        ;MSW löschen
  401.         rts
  402.  
  403.  
  404. **
  405. ** In ein SID-Register schreiben
  406. ** d0.w: Registernummer ($00-$1f)
  407. ** d1.b: Byte
  408. **
  409. ** Darf das obere Wort von d0 und d1 nicht verändern!
  410. **
  411.  
  412. WriteTo6581    move.b    d1,(Registers,d0.w)
  413.         cmp.w    #SIDTYPE_CARD,CurrentSIDType
  414.         beq    WriteCard
  415.         cmp.w    #SIDTYPE_A64,CurrentSIDType
  416.         beq    WriteA64
  417.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  418.         beq    WritePSID
  419.         rts
  420.  
  421. WriteCard    lea    $a00001,a0    ;SID-Karte
  422.         move.b    d1,(a0,d0.w*2)
  423.         rts
  424.  
  425. WriteA64    tst.l    SIDHandle
  426.         beq    1$
  427.         move.l    a6,-(sp)
  428.         move.l    _SID6581Base,a6
  429.         move.l    SIDHandle,a1    ;d0: Regnum, d1: Byte
  430.         jsr    SID_WriteReg(a6)
  431.         move.l    (sp)+,a6
  432.         moveq    #0,d0
  433.         moveq    #0,d1
  434. 1$        rts
  435.  
  436. WritePSID    tst.b    PSIDOpened
  437.         beq    1$
  438.         move.l    a6,-(sp)
  439.         move.l    _PlaySidBase,a6
  440.         move.l    $15a(a6),a0    ;Code im C64-RAM der playsid.library ändern
  441.         move.b    d0,$1004(a0)
  442.         move.b    d1,$1002(a0)
  443.         moveq    #1,d0        ;Aufruf der Play-Routine erzwingen
  444.         jsr    _LVOForwardSong(a6)
  445.         move.l    (sp)+,a6
  446.         moveq    #0,d0
  447.         moveq    #0,d1
  448. 1$        rts
  449.  
  450.  
  451. **
  452. ** SID-Register (nur als Backup für SAM und Snapshots)
  453. **
  454.  
  455. Registers    ds.b    32
  456.  
  457.  
  458. **
  459. ** Konstanten
  460. **
  461.  
  462. IntName        dc.b    "Frodo SID VBI",0
  463.  
  464.  
  465. **
  466. ** Initialisierte Daten
  467. **
  468.  
  469.         SECTION    "DATA",DATA
  470.  
  471. VBInterrupt    dc.l    0,0
  472.         dc.b    NT_INTERRUPT,0
  473.         dc.l    IntName
  474. SIDHandle    dc.l    0    ;Handle für die 6581sid.library und Flag, daß sie verfügbar ist
  475.         dc.l    IntProc
  476.  
  477. SIDType        dc.w    0    ;Prefs: Art der SID-Emulation
  478.  
  479. PSIDHeader    dc.b    "PSID"    ;Dummy-Modul-Header für playsid.library
  480.         dc.w    2
  481.         dc.w    PSIDHeaderEnd-PSIDHeader
  482.         dc.w    $1000    ;Load
  483.         dc.w    $1000    ;Init
  484.         dc.w    $1001    ;Play
  485.         dc.w    1
  486.         dc.w    1
  487.         dc.l    0
  488.         ds.b    HEADERINFO_SIZE
  489.         ds.b    HEADERINFO_SIZE
  490.         ds.b    HEADERINFO_SIZE
  491.         dc.w    0
  492.         dc.l    0
  493. PSIDHeaderEnd
  494.                     ;Init:
  495.         dc.b    $60        ; rts
  496.  
  497.                     ;Play:
  498.         dc.b    $a9,0        ; lda #xx
  499.         dc.b    $8d,0,$d4    ; sta $d4xx
  500.         dc.b    $60        ; rts
  501. PSIDEnd
  502.  
  503.  
  504. **
  505. ** Nicht initialisierte Daten
  506. **
  507.  
  508.         SECTION    "BSS",BSS
  509.  
  510. CurrentSIDType    ds.w    1    ;Augenblicklicher SID-Typ
  511.  
  512. SIDInited    ds.b    1    ;Flag: InitSID wurde aufgerufen
  513. PSIDOpened    ds.b    1    ;Flag: playsid.library ist initialisiert
  514.  
  515.         END
  516.